﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Drawing.Design;
using System.Collections;
using Atechnology.glassCAD.Shapes.Dxf;
using System.Windows.Forms.Design;
using System.IO;
using System.Windows.Forms;

namespace Atechnology.glassCAD.Shapes
{
    public class SelectFile : UITypeEditor {
        private IWindowsFormsEditorService edSvc = null;
        
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) {
            if(context != null && context.Instance != null) {
                return UITypeEditorEditStyle.Modal;
            }
            return base.GetEditStyle(context);
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object Value) {
            System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
            if(ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK) {                
                return ofd.FileName;
            }
            return String.Empty;
            /*
            edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            using(ListBoxForm viewForm = new ListBoxForm(edSvc, context.Instance as clsModel, (clsConstructionColor)Value)) {
                viewForm.selectedConstructionColor = (clsConstructionColor)Value;
                viewForm.ExpandAll();
                viewForm.isStart = true;
                edSvc.DropDownControl(viewForm);
                if(viewForm.selectedConstructionColor != null)
                    return viewForm.selectedConstructionColor;
                return Value;
            }*/
        }
    }

	[Serializable()]
	public class GlassItems99 : CommonGlass
	{
        Atechnology.glassCAD.Shapes.Dxf.Dxf ObjDxf = new Atechnology.glassCAD.Shapes.Dxf.Dxf();

		#region переменные и свойства класса
        [Category("Геометрия"), DisplayName("B1"), Description(""), Position(11)]
        public virtual float B1 {
            get {
                return b1;
            }
            set {
                if(value >= 0) {
                    b1 = value;
                    GetSizes();
                }
            }
        }
        [Category("Геометрия"), DisplayName("B2"), Description(""), Position(12)]
        public virtual float B2 {
            get {
                return b2;
            }
            set {
                if(value >= 0) {
                    b2 = value;
                    GetSizes();
                }
            }
        }
        [Category("Геометрия"), DisplayName("B3"), Description(""), Position(13)]
        public virtual float B3 {
            get {
                return b3;
            }
            set {
                if(value >= 0) {
                    b3 = value;
                    GetSizes();
                }
            }
        }
        [Category("Геометрия"), DisplayName("B4"), Description(""), Position(14)]
        public virtual float B4 {
            get {
                return b4;
            }
            set {
                if(value >= 0) {
                    b4 = value;
                    GetSizes();
                }
            }
        }

        public override void AcceptVisitor(IShapeVisitor visitor)
        {
            visitor.Visit(this);
        }


        [Category("Геометрия"), DisplayName("L"), Description("Ширина фигуры (L)"), Position(1)]
        [ReadOnly(true)]
        public override float L
        {
            get
            {
                return base.L;
            }
            set
            {
                base.L = value;
            }
        }

        [Category("Геометрия"), DisplayName("H"), Description("Высота фигуры (H)"), Position(1)]
        [ReadOnly(true)]
        public override float H
        {
            get
            {
                return base.H;
            }
            set
            {
                base.H = value;
            }
        }

        [Category("Геометрия"), DisplayName("Файл"), Editor(typeof(SelectFile), typeof(UITypeEditor))]
        public string FileName {
            get {
                return FileNameDxf;
            }
            set {
                FileNameDxf = value;
                if(FileNameDxf != null && FileNameDxf != "")
                    this.LoadFromFile(FileNameDxf);
                //using(StreamReader sr = new StreamReader(new FileStream(FileNameDxf, FileMode.Open))) {
                //    this.LoadFromString(sr.ReadToEnd());
                //}
                
            }
        }
        #endregion

        private void LoadFromFile(string fileName)
        {
            try
            {
                java.io.File file = new java.io.File(fileName);
                ObjDxf.Load(file.getAbsoluteFile());
                
            }
            catch(Exception e)
            {
                string str = e.Message;
                Exception innerEx = e.InnerException;
                while (innerEx != null)
                {
                    str += " |||| " + innerEx.Message;
                    innerEx  = innerEx.InnerException;
                }
                MessageBox.Show(str);
            }
//            StrDxf = Dxf;
            //L = (int)this.GetRectangle().Width;
            //H = (int)this.GetRectangle().Height;
            L = (int)ObjDxf.CalcRect(Corner.LeftDown).Width + 1;
            H = (int)ObjDxf.CalcRect(Corner.LeftDown).Height + 1;
            
        }

        // Необходим для сериализации в XML и десериализации из XML
        public GlassItems99()
        {            
        }

		public GlassItems99(Param p) : base(p)
		{
			ID = 99;
			Shape.GetShapeBasicParams(ProgramType.Glass, ID, ref Name, ref Group, ref IDGroup);
            Group = "Шаблоны";
            Name = "DXF";
		}

        //public override void SetGabarite(int l, int h) {
        //    base.SetGabarite(l, h);

        //    if(StrDxf != String.Empty) {
        //        this.LoadFromString(StrDxf);                
        //    }
        //}
        public override void SetGabarite(int l, int h)
        {
            base.SetGabarite(l, h);

            if (FileName != string.Empty)
            {
                this.LoadFromFile(FileName);
            }
        }

        override internal void GetSizes() {
            base.GetSizes();

            RectangleF rect = ObjDxf.CalcRect(Corner.LeftDown); // GetRectangle();
            param.Width = (int)L;
            param.Height = (int)H;
            param.WidthFull = (int)(L + b1 + b3);
            param.HeightFull = (int)(H + b2 + b4);
		}

        //public void LoadFromString(string Dxf){
        //    ObjDxf.Load(Dxf);
        //    StrDxf = Dxf;
        //    //L = (int)this.GetRectangle().Width;
        //    //H = (int)this.GetRectangle().Height;
        //    L = (int)ObjDxf.CalcRect(Corner.LeftDown).Width + 1;
        //    H = (int)ObjDxf.CalcRect(Corner.LeftDown).Height + 1;

        //}

        override protected void CalcAllVynosy(Graphics graphics, bool withletters)
        {
            Font drawFont = new Font("Tahoma", fontsize);
            float fontheight = graphics.MeasureString("0", drawFont).Height;

            max_vynos_snizu = vynossize;
            float HStrLen = graphics.MeasureString((withletters == true ? "H=" : "") + H.ToString(), drawFont).Width + vynossize;
            float B1StrLen = graphics.MeasureString((withletters == true ? "B1=" : "") + B1.ToString(), drawFont).Width;
            max_vynos_sleva = vynossize + Math.Max(HStrLen, B1StrLen);
            float B4StrLen = graphics.MeasureString((withletters == true ? "B4=" : "") + B4.ToString(), drawFont).Width + vynossize;
            max_vynos_sprava = vynossize + B4StrLen;

            b1vynossize = graphics.MeasureString((withletters == true ? "B1=" : "") + b1.ToString(), drawFont).Width;
            b3vynossize = graphics.MeasureString((withletters == true ? "B3=" : "") + b3.ToString(), drawFont).Width;
            b2vynossize = graphics.MeasureString((withletters == true ? "B2=" : "") + B2.ToString(), drawFont).Width;
        }

        public override RectangleF GetRectangle()
        {
            RectangleF dxfRect = ObjDxf.CalcRect(Corner.LeftUp);           
            return new RectangleF(dxfRect.X, dxfRect.Y - H, L + B3, H + B4);

        }

        override public void ShapePaint(Graphics graphics, bool withvynos, bool withletters, bool withtext, bool withmarking, Color bodyColor)
        {
            if (ObjDxf.Count == 0) return;

            if (error)
            {
                PrintError(graphics);
                return;
            }
            else
            {
                float VK = System.Math.Min((PictureBoxWidth * 0.8F) / (L), (PictureBoxHeight * 0.8F) / (H));
                Pen p = new Pen(Color.DarkGray);

                Rectangle rec = new Rectangle();
                rec.Width = (int)((L) * VK);
                rec.Height = (int)((H) * VK);
                rec.X = (PictureBoxWidth - rec.Width) / 2;
                rec.Y = (PictureBoxHeight - rec.Height) / 2;
                graphics.DrawRectangle(p, rec);

                Font drawFont = new Font("Tahoma", fontsize);
                SolidBrush drawBrush = new SolidBrush(Color.Black);

 //               if (StrDxf == String.Empty)
                //{
                //    graphics.DrawString("DXF", drawFont, drawBrush, rec.X + rec.Width / 2, rec.Y + rec.Height / 2);
                //}
                //else
                {
                    //graphics.DrawString((l + b1 + b3).ToString(), drawFont, drawBrush, rec.X + rec.Width / 2, rec.Y + rec.Height + 10);
                    //graphics.DrawString((h + b2 + b4).ToString(), drawFont, drawBrush, rec.X - 30, rec.Y + rec.Height / 2);

                    //rec.X += (int)(B1 * VK);
                    //rec.Y += (int)(B2 * VK);
                    //rec.Width -= (int)((B1 + B3) * VK);
                    //rec.Height -= (int)((B2 + B4) * VK);
                    graphics.DrawRectangle(p, rec);

                    //graphics.DrawString((l).ToString(), drawFont, drawBrush, rec.X + rec.Width / 2, rec.Y + rec.Height + 10);
                    //graphics.DrawString((h).ToString(), drawFont, drawBrush, rec.X - 30, rec.Y + rec.Height / 2);

                    Shapes.Dxf.DxfDrawer.State state = new Atechnology.glassCAD.Shapes.Dxf.DxfDrawer.State();
                    state.translateX = rec.X;
                    state.translateY = (rec.Y + rec.Height);
                    //state.ofsX = -GetRectangle().X;
                    //state.ofsY = -GetRectangle().Y;
                    state.ofsX = -ObjDxf.CalcRect(Corner.LeftDown).X;
                    state.ofsY = -ObjDxf.CalcRect(Corner.LeftDown).Y;
                    //state.scaleX = rec.Width / (float)GetRectangle().Width;
                    //state.scaleY = -rec.Height / (float)GetRectangle().Height;
                    state.scaleX = (float)rec.Width / (float)ObjDxf.CalcRect(Corner.LeftDown).Width;
                    state.scaleY = -(float)rec.Height / (float)ObjDxf.CalcRect(Corner.LeftDown).Height;

                    Shapes.Dxf.DxfDrawer.Draw(graphics, ObjDxf, state, Color.White);
                }

                // рисование отступов
                DrawGeometry.DrawVynosVniz(graphics, rec.X - b1vynossize, rec.Y + rec.Height, b1vynossize, vynossize, "B1=", b1.ToString(), withletters, fontsize, vynossize);
                DrawGeometry.DrawVynosVniz(graphics, rec.X + rec.Width, rec.Y, b3vynossize, vynossize, "B3=", b3.ToString(), withletters, fontsize, vynossize);
                DrawGeometry.DrawVynosSleva(graphics, rec.X + vynossize, rec.Y - vynossize, vynossize, vynossize, "B2=", b2.ToString(), withletters, fontsize, vynossize);
                DrawGeometry.DrawVynosSprava(graphics, rec.X + rec.Width, rec.Y + rec.Height, vynossize, vynossize, "B4=", b4.ToString(), withletters, fontsize, vynossize);
                DrawGeometry.DrawVynosVniz(graphics, rec.X, rec.Y + rec.Height, rec.Width, vynossize, "L=", l.ToString(), withletters, fontsize, vynossize);
                DrawGeometry.DrawVynosSleva(graphics, rec.X, rec.Y, vynossize, rec.Height, "H=", h.ToString(), withletters, fontsize, vynossize);
            }

        }

        public override Atechnology.glassCAD.Shapes.Dxf.Dxf[] GetDxfContours()
        {
            if (this.isInverted)
            {
                return this.GetInvert().GetDxfContours();
            }

            return new Atechnology.glassCAD.Shapes.Dxf.Dxf[] { ObjDxf };
        }

        public override void DrawState(Graphics graphics, Atechnology.glassCAD.Shapes.Dxf.DxfDrawer.State state, Color fillColor)
        {
            if (ObjDxf.Count == 0) return;

            if (this.isInverted)
            {
                this.GetInvert().DrawState(graphics, state, fillColor);
                return;
            }

            Shapes.Dxf.DxfDrawer.Draw(graphics, ObjDxf, state, fillColor);
        }

        public override double GetHorizontalOffset()
        {
            return B1;
        }

        public override double GetVerticalOffset()
        {
            return B2;
        }

		public override void Calc()
		{
			base.Calc();
			param.perimetrs.Clear();
			param.squares.Clear();

            Perimetr per = new Perimetr();
            foreach(Primitive pr in this.ObjDxf) {
                per.sides.Add((float)pr.Length());
            }
            param.perimetrs.Add(per);

            param.squares.Add(new Square(L * H));
		}

        public override Shape GetInvert()
        {
            GlassItems99 InvertShape = new GlassItems99(new Param());
            //InvertShape.LoadFromString(this.StrDxf);
            InvertShape.LoadFromFile(this.FileName);
            InvertShape.B4 = this.B2;
            InvertShape.B3 = this.B1;
            InvertShape.B2 = this.B4;
            InvertShape.B1 = this.B3;

            InvertShape.ObjDxf.MirrorVertical(GetRectangle().X + GetRectangle().Width / 2);
            //InvertShape.ObjDxf.MirrorVertical(ObjDxf.CalcRect(Corner.LeftDown).X + ObjDxf.CalcRect(Corner.LeftDown).Width / 2);
            
            return InvertShape;
        }

        public override Atechnology.Spreading.Collections.colLine GetConturForSpreading()
        {
            Atechnology.Spreading.Collections.colLine resiult = new Atechnology.Spreading.Collections.colLine();

            //float dx = GetRectangle().X;
            //float dy = GetRectangle().Y;
            float dx = ObjDxf.CalcRect(Corner.LeftDown).X;
            float dy = ObjDxf.CalcRect(Corner.LeftDown).Y;


           
            foreach(Primitive pr in this.ObjDxf) {
                if(pr is Line) {
                    Line l = pr as Line;
                    Atechnology.Spreading.Classes.clsLine clsLine1 = new Atechnology.Spreading.Classes.clsLine(l.Start.X - dx, l.Start.Y - dy, l.End.X - dx, l.End.Y - dy);
                    resiult.Add(clsLine1);
                }
                if(pr is Arc) {

                }
            }

            return resiult;
        }

        public override List<string> GetAnzData() {

            if (this.isInverted)
                return this.GetInvert().GetAnzData();


            List<string> anz = new List<string>();
            if(ObjDxf.Count == 0) 
                return anz;

            //Size plateSize = new Size((int)(ObjDxf.CalcRect(Corner.LeftDown).Size.Width + b1 + b3), (int)(ObjDxf.CalcRect(Corner.LeftDown).Size.Height + b2 + b4));
            SizeF plateSize = new SizeF((ObjDxf.CalcRect(Corner.LeftDown).Size.Width + b1 + b3), (ObjDxf.CalcRect(Corner.LeftDown).Size.Height + b2 + b4));
            //Point shapePos = new Point(-(int)GetRectangle().X,-(int)GetRectangle().Y);
            PointF shapePos = new PointF(-ObjDxf.CalcRect(Corner.LeftDown).X, -ObjDxf.CalcRect(Corner.LeftDown).Y);
            //Point shapePos = new Point(0, 0);


            // Округляю размеры в anz, т.к. формат стола резки иногда гонит на нецелых размерах, и мне пришлось округлить размеры в 41, 27 шейпе и подобных...
            anz.Add(FloatToN10((int)plateSize.Width) + " " + FloatToN10((int)plateSize.Height) + "  0");
            anz.Add("1 0 0 2");
            anz.Add(FloatToN10(0));
            anz.Add(FloatToN10(0));
            anz.Add("1 0 0 2");
            anz.Add(FloatToN10((int)plateSize.Width));
            anz.Add(FloatToN10((int)plateSize.Height));

            int n = 0;
            foreach(Primitive p in ObjDxf) {
                if(p is Line) {
                    //anz.Add(String.Format("1 {0} 2 10", ++n));
                    anz.Add("2 0 0 2");
                    anz.Add(FloatToN10((p as Line).Start.X + shapePos.X));
                    anz.Add(FloatToN10((p as Line).Start.Y + shapePos.Y));
                    anz.Add(FloatToN10((p as Line).End.X + shapePos.X));
                    anz.Add(FloatToN10((p as Line).End.Y + shapePos.Y));
                } else if(p is Arc) {
                    //anz.Add(String.Format("3 {0} 2 10", ++n));
                    anz.Add("3 0 0 2");
                    anz.Add(FloatToN10((p as Arc).Center.X + shapePos.X));
                    anz.Add(FloatToN10((p as Arc).Center.Y + shapePos.Y));
                    anz.Add(FloatToN10((p as Arc).Radius));
                    anz.Add(FloatToN10((p as Arc).Start / 180 * (float)System.Math.PI));
                    anz.Add(FloatToN10((p as Arc).End / 180 * (float)System.Math.PI));
                    anz.Add(FloatToN10(p.getStart().X + shapePos.X));
                    anz.Add(FloatToN10(p.getStart().Y + shapePos.Y));
                    anz.Add(FloatToN10(p.getEnd().X + shapePos.X));
                    anz.Add(FloatToN10(p.getEnd().Y + shapePos.Y));
                }
            }
            anz.Add("7 0 0 7");
            anz.Add("1.000000");
            anz.Add("1.000000");

            return anz;
        }

        string FloatToN10(float value) {
            return value.ToString("0.000000", System.Globalization.CultureInfo.InvariantCulture);
        }
	}
}
